package irc;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.Connector;

/**
 * Klasa główna biblioteki. To własnie metod tej klasy powinien używać klient
 * w swojej aplikacji do obslugi protokołu irc.
 * @author adrian
 */
public class IrcClient implements MessageListener {

    /**
     * Pole connectora
     */
    private Connector connect = null;
    private String username = new String("Irc");
    private String nick = new String("IrcClient");
    private HashMap<String, Channel> channels;
    private LinkedList<MessageListener> messageListeners;

    /**
     * Konstruktor klienta
     * Ustawia pierwszy kanał - kanał serwera, w którym widoczne są wszystkie komunikaty
     */
    public IrcClient() {
        Channel serverChannel = ServerChannel.getInstance(); // tylko jeden kanał serwera.        
        channels = new HashMap<String, Channel>();
        channels.put("Server",serverChannel);
        //Nowa lista listenerów
        messageListeners = new LinkedList<MessageListener>();
    }

    /**
     * Metoda łaczy klienta z serwerem irc o podanym adresie nasłuchującym na podanym porcie. Przed użyciem
     * nalezy ustawić username i nick
     * @author adrian
     * @param address Adres serwera do połączenia
     * @param port Numer portu.
     * @exception Exception wyjątek zostanie wyrzucony, gdy nie metoda nie nawiąże połączenia. Treść wyjątku zostanie
     * przesłana do strumienia err.
     */
    public void connectToHost(String address, int port) throws Exception {
        if ((username == null || nick == null) || (username.isEmpty() || nick.isEmpty())) {
            throw new Exception("Musisz najpierw zainicjalizować nick i username");
        } else {
            try {
                connect = new Connector(address, port,this);  
                send("NICK "+ nick +"\n");
                send("USER "+ username +"\n");               
            } catch (Exception ex) {
                throw new Exception(ex);
            }
        }
    }

    /**
     * Metoda rozłącza z ostatnio połączonym hostem.
     * @author adrian
     * @return zwraca prawdę, gdy operacja zakończy się powodzeniem, inaczej fałsz.
     */
    public boolean disconnectFromHost() {
        try {
            connect.disconnect();
        } catch (Exception ex) {
            Logger.getLogger(IrcClient.class.getName()).log(Level.SEVERE, null, ex);
        }
        return true;//póki co true           
    } 

    /**
     * Zmienia nick użytkownika
     * @param nick Nowy nick jako String
     */
    public void setNick(String nick) {
        this.nick = nick;        
    }

    /**
     * Pobiera nick użytkownika
     * @return nick jako String
     */
    public String getNick() {        
        return nick;        
    }

    /**
     * Ustawia nazwę użytkownika
     * @param username
     */
    public void setUsername(String username) {
        this.username = username;
    }

    /**
     * Pobiera nazwę użytkownika.
     * @return
     */
    public String getUsername() {
        return username;
    }
    
    /**
     * 
     * @param ml 
     */
    public void addMessageListener(MessageListener ml){
        messageListeners.add(ml);
    }
    
    /**
     * 
     * @param ml 
     */
    public void removeMessageListener(MessageListener ml){
        messageListeners.remove(ml);
    }

    /**
     * Metoda służąca do wysyłania wiadomości do serwera.
     * @param String msg - wiadomość do przesłania.
     * @todo obsłużyć wyjątek klasą loggera
     */
    public void send(String msg) {
        try {
            connect.sendToServer(msg);
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }

    /**
     * Metoda odbierająca wiadomości z serwera wywoływana za kazdym razem, gdy
     * jakaś wiadomość zostanie wysłana przez serwer bądź też rozmówcę - innego 
     * klienta w CTCP.
     * 
     * @todo otrzymywanie wiadomości z serwera.
     * @todo opracować sposób w jaki będą odbierane wiedomości z serwera.
     */
    public void receivedCommand(String cmd) {
        for (MessageListener messageListener : messageListeners) {
            messageListener.getMessageLine(cmd);
        }
    }

    public static void main(String[] args) throws Exception {
        IrcClient irc = new IrcClient();
        irc.addMessageListener(irc);
        irc.setNick("JrcLib");        
        irc.setUsername("IrcLib Irc Lib Adrian");
//        irc.send("CHANNEL #help");
//        irc.connectToHost("quider.pl", 6667);
        irc.connectToHost("krakow.irc.pl", 6667);
        irc.send("JOIN #help \n");
        System.out.println("Tworze skaner:");
        Scanner s = new Scanner(System.in);
        while(true){
            if(s.hasNext())  {
                String nextLine = s.nextLine();
                irc.send(nextLine);
            }
        }
    }

    /**
     * 
     * @param cmd
     * @return 
     */
    public String getMessageLine(String cmd) {
        System.out.println(cmd);
        return "";
    }
}
